package com.yupi.yupao.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yupi.yupao.common.BaseResponse;
import com.yupi.yupao.common.DeleteRequest;
import com.yupi.yupao.common.ErrorCode;
import com.yupi.yupao.common.ResultUtils;
import com.yupi.yupao.exception.BusinessException;
import com.yupi.yupao.model.domain.Team;
import com.yupi.yupao.model.domain.User;
import com.yupi.yupao.model.domain.UserTeam;
import com.yupi.yupao.model.dto.TeamQuery;
import com.yupi.yupao.model.request.TeamAddRequest;
import com.yupi.yupao.model.request.TeamJoinRequest;
import com.yupi.yupao.model.request.TeamQuitRequest;
import com.yupi.yupao.model.request.TeamUpdateRequest;
import com.yupi.yupao.model.vo.TeamUserVO;
import com.yupi.yupao.service.TeamService;
import com.yupi.yupao.service.UserService;
import com.yupi.yupao.service.UserTeamService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 队伍接口
 *
 * @author 曹宏福
 * @version 1.0
 */
@SuppressWarnings({"all"}) //禁止所有警告
@RestController
@RequestMapping("/team")
@CrossOrigin(origins = {"http://localhost:3000"})
@Slf4j
public class TeamController {
    @Resource
    private UserService userService;

    @Resource
    private TeamService teamService;

    @Resource
    private UserTeamService userTeamService;

    /**
     * 添加队伍(创建队伍)
     *
     * @param teamAddRequest
     * @return
     */
    @ApiOperation(value = "创建队伍", notes = "传入TeamAddRequest请求体返回增加的teamId", response = BaseResponse.class)
    @PostMapping("/add")
    public BaseResponse<Long> addTeam(@RequestBody TeamAddRequest teamAddRequest, HttpServletRequest request) {
        if (teamAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //获取当前登录用户
        User loginUser = userService.getLoginUser(request);
        Team team = new Team();
        //spring框架的BeanUtils 复制
        BeanUtils.copyProperties(teamAddRequest, team);
        //service业务逻辑，增加队伍
        long teamID = teamService.addTeam(team, loginUser);
        return ResultUtils.success(teamID);
    }

    /**
     * 更改队伍信息请求接口
     *
     * @param teamUpdateRequest
     * @param request
     * @return
     */
    @PostMapping("/update")
    public BaseResponse<Boolean> updateTeam(@RequestBody TeamUpdateRequest teamUpdateRequest, HttpServletRequest request) {
        if (teamUpdateRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //获取登录用户
        User loginUser = userService.getLoginUser(request);
        //更新队伍信息业务逻辑
        boolean updateTeam = teamService.updateTeam(teamUpdateRequest, loginUser);
        if (!updateTeam) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新失败");
        }
        return ResultUtils.success(true);
    }

    /**
     * 获取队伍 根据队伍id
     *
     * @param id
     * @return
     */
    @GetMapping("/get")
    public BaseResponse<Team> getTeamById(long id) {
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = teamService.getById(id);
        if (team == null) {
            throw new BusinessException(ErrorCode.NULL_ERROR);
        }
        return ResultUtils.success(team);
    }

    /**
     * 查询队伍信息列表:返回已经加入的队伍人数给前端展示 java8特性 看代码
     *
     * @param teamQuery:队伍永通查询请求体
     * @return
     */
    @GetMapping("/list")
    public BaseResponse<List<TeamUserVO>> listTeams(TeamQuery teamQuery, HttpServletRequest request) {
        //判空
        if (teamQuery == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //只有管理员才能查看加密还有非公开的房间
        boolean admin = userService.isAdmin(request);
        //1、查询队伍列表->所有
        List<TeamUserVO> teamList = teamService.listTeams(teamQuery, admin);
        //获取队伍ID
        List<Long> teamIdList = teamList.stream().map(TeamUserVO::getId).collect(Collectors.toList());
        //2、判断当前用户是否已经加入队伍
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        try {
            User loginUser = userService.getLoginUser(request);
            userTeamQueryWrapper.eq("userId", loginUser.getId());
            userTeamQueryWrapper.in("teamId", teamIdList);
            //查询到的是登录用户的关联队伍信息集合
            List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);
            //队伍id集合->
            Set<Long> hasJoinTeamIdSet =
                    userTeamList.stream().map(UserTeam::getTeamId).collect(Collectors.toSet());
            /**
             * 遍历队伍列表中标记出当前登录用户已经加入的队伍
             * 方便前端根据这个标记显示不同的操作按钮或提示信息
             */
            for (TeamUserVO team : teamList) {
                //判断用户是否已加入当前队伍
                boolean hasJoin = hasJoinTeamIdSet.contains(team.getId());
                team.setHasJoin(hasJoin);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //3、查询每个队伍已加入的队伍的人数
        QueryWrapper<UserTeam> userTeamJoinQueryWrapper = new QueryWrapper<>();
        userTeamJoinQueryWrapper.in("teamId", teamIdList);
        List<UserTeam> userTeamList = userTeamService.list(userTeamJoinQueryWrapper);
        //队伍 id => 加入这个队伍的用户列表
        //根据队伍id进行分组 键:teamID 值：用户队伍关系类
        Map<Long, List<UserTeam>> teamIdUserTeamList =
                userTeamList.stream().collect(Collectors.groupingBy(UserTeam::getTeamId));
        //设置每个队伍都加入了多少人
        for (TeamUserVO team : teamList) {
            team.setHasJoinNum(teamIdUserTeamList.getOrDefault(team.getId(), new ArrayList<>()).size());
        }
        return ResultUtils.success(teamList);
    }


    /**
     * 查询分页
     *
     * @param teamQuery
     * @return
     */
    @GetMapping("/list/page")
    public BaseResponse<Page<Team>> listTeamsByPage(TeamQuery teamQuery) {
        if (teamQuery == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Team team = new Team();
        BeanUtils.copyProperties(teamQuery, team); //属性名相同就会复制
        Page<Team> page = new Page<>(teamQuery.getPageNum(), teamQuery.getPageSize());
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>(team);
        Page<Team> resultPage = teamService.page(page, queryWrapper);
        return ResultUtils.success(resultPage);
    }


    /**
     * 用户加入队伍接口
     *
     * @param teamJoinRequest
     * @param request
     * @return
     */
    @PostMapping("/join")
    public BaseResponse<Boolean> joinTeam(@RequestBody TeamJoinRequest teamJoinRequest, HttpServletRequest request) {
        //判空
        if (teamJoinRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //获取登录用户
        User loginUser = userService.getLoginUser(request);
        //调用用户加入队伍接口的逻辑接口
        boolean joinTeam = teamService.joinTeam(teamJoinRequest, loginUser);
        if (!joinTeam) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "用户加入队伍失败");
        }
        return ResultUtils.success(true);
    }

    /**
     * 退出队伍接口
     *
     * @param teamQuitRequest
     * @param request
     * @return
     */
    @PostMapping("/quit")
    public BaseResponse<Boolean> quitTeam(@RequestBody TeamQuitRequest teamQuitRequest, HttpServletRequest request) {
        //判空
        if (teamQuitRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //获取登录用户
        User loginUser = userService.getLoginUser(request);
        //调用用户退出接口的逻辑接口
        boolean result = teamService.quitTeam(teamQuitRequest, loginUser);
        return ResultUtils.success(true);
    }

    /**
     * 解散队伍->删除队伍
     *
     * @param deleteRequest : 通用删除请求体
     * @param request
     * @return
     */
    @PostMapping("/delete")
    public BaseResponse<Boolean> deleteTeam(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        //判空
        if (deleteRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //获取登录用户
        User loginUser = userService.getLoginUser(request);
        boolean bo = teamService.deleteTeam(deleteRequest.getId(), loginUser);
        if (!bo) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "队伍解散失败");
        }
        return ResultUtils.success(true);
    }

    /**
     * 获取我创建的队伍->逻辑是
     *
     * @param teamQuery: 队伍查询封装类：数据传输对象类
     * @param request:
     * @return 脱敏后的用户列表
     */
    @GetMapping("/list/my/create")
    public BaseResponse<List<TeamUserVO>> listMyCreateTeams(TeamQuery teamQuery, HttpServletRequest request) {
        if (teamQuery == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //获取当前登录用户信息
        User loginUser = userService.getLoginUser(request);
        boolean admin = userService.isAdmin(request);
        teamQuery.setUserId(loginUser.getId());
        //获取队伍列表信息 默认都可以查询自己创建的队伍 todo 优化返回已加入队伍的人数 finished
        List<TeamUserVO> teamList = teamService.listTeamsNew(teamQuery, true);
        return ResultUtils.success(teamList);
    }

    /**
     * 获取我加入的队伍
     * todo 测试只获取我加入的队伍 用户二 创建了 队伍 1 5 用户关系表显示 用户二还加入了队伍5 所以最后查询出来的队伍是5->finished
     * todo 优化逻辑 返回我加入队伍的人数
     * @param teamQuery: 队伍查询封装类：数据传输对象类
     * @param request:
     * @return :队伍和用户信息封装类（脱敏）
     */
    @GetMapping("/list/my/join")
    public BaseResponse<List<TeamUserVO>> listMyJoinTeams(TeamQuery teamQuery, HttpServletRequest request) {
        if (teamQuery == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //获取登录用户信息
        User loginUser = userService.getLoginUser(request);
        //查询我加入的队伍->将我创建的和我加入的分开查询
        //查询用户关联表 取出所有我加入的和我创建的队伍id 再将我创建的队伍id排除
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", loginUser.getId());
        //获取关联表所有该用户的信息
        List<UserTeam> userTeamList = userTeamService.list(queryWrapper);
        //取出userId的所有队伍Id并进行分组
        // 取出不重复的队伍 id
        // teamId userId
        // 1, 2
        // 1, 3
        // 2, 3
        // result
        // 1 => 2, 3
        // 2 => 3
        /**
         * 键: 队伍id
         * 值：关联表用户信息集合
         */
        Map<Long, List<UserTeam>> listMap = userTeamList.stream().collect(Collectors.groupingBy(item -> {
            return item.getTeamId();
        }));
        //得到当前用户在关联表中的队伍id【2,5】
        List<Long> idList = new ArrayList<>(listMap.keySet());
        //获取用户Id 查询所有当前用户创建的队伍id列表
        teamQuery.setUserId(loginUser.getId());
        //获取我创建的队伍id[1,2]
        final boolean admin = userService.isAdmin(request);
        List<Long> teamByMyselfId = teamService.getTeamByMyself(teamQuery, admin);
        //将我创建的队伍从我加入的队伍中移除
        //流式计算移除 得到[5]
        List<Long> result = idList.stream().filter(id -> {
            return !teamByMyselfId.contains(id);
        }).collect(Collectors.toList());
        //设置队伍id列表
        teamQuery.setIdList(result);
        //再次查询过滤所有我加入的队伍
        List<TeamUserVO> teamUserVOS = teamService.listTeams(teamQuery, true);
        return ResultUtils.success(teamUserVOS);
    }


}
